#ifndef __GLF_EPHEMERAL_ALLOCATOR_H_INCLUDED__
#define __GLF_EPHEMERAL_ALLOCATOR_H_INCLUDED__

/** EphemeralAllocator
	The ephemeral allocator is meant to minimize concurrency cost by providing an allocator per thread
	which will do allocation inside an owned allocation block. Allocation complexity is reduce to 0(1)
	since allocation are always push back in the active block. Once the block is full, the allocator 
	release it and ask for a new one in the allocation block manager that is shared by all thread. To
	minimize concurrency in that manager an hash table in which we spread incoming block and request to
	allocate one is used. If there's collision while pushing and popping block an spscUnboundedQueue 
	could be used to remove collision between push and pop letting one collision between pops or 
	pushes. The only synchronization system used are atomic, no mutex or other synchronization solution 
	are	used.
	The memory block are returned to the block manager once all references (allocation, allocator) to it
	are dropped. This allow us to avoid any kind fragmentation management. The drawback of this 
	implementation is that an allocation kept for a while will generate internal fragmentation that will
	last as long as that last allocation.

	Allocation can be freed on any other thread without any additional cost.

	Performance compared to the standard allocator:
		On PC:
			Break even on single threading test.
			40% better on heavy multithreading test 5 core out of 6 doing massive allocation deallocation. 
		On iOS (iPad2):
			5 times faster on a single threading test.
			Same as single threading. 
		No noticeable concurrency issue in both implementations.
*/
#include <glf/mem/allocator.h>

namespace glf 
{

class EphemeralAllocatorBase
{
protected:
	static void* internal_new(size_t cnt);
	static void internal_delete(void* const ptr);
};

template <typename T>
class EphemeralAllocator
	: public Allocator<T, EphemeralAllocatorBase >
{
};


void* allocateEphemeralAllocation(size_t);
void freeEphemeralAllocation(void*);
void cleanupEphemeralFreeBlocks();

inline
void* EphemeralAllocatorBase::internal_new(size_t cnt)
{
	return allocateEphemeralAllocation(cnt);
}

inline
void EphemeralAllocatorBase::internal_delete(void* const ptr)
{
	freeEphemeralAllocation(ptr);
}

} // end of namespace glf

#endif //__GLF_EPHEMERAL_ALLOCATOR_H_INCLUDED__